package a02;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;

public class SaveGameManager<M> {

    private RegularControl<M> control;
    private boolean cancel = false;

    public SaveGameManager(RegularControl<M> control) {
	this.control = control;
    }

    public void save() {
	writeSavegameFile(control.getBoard().getGame());
    }

    @SuppressWarnings("unchecked")
    // TODO SUPPRESS WARNINGS WEGEN GENERIC
    public void load() {
	RegularGame<M> game = null;
	Object o = null;

	o = readSavegameObject();
	if (o instanceof TicTacToe || o instanceof Vier || o instanceof Othello
		|| o instanceof Go)
	    game = (RegularGame<M>) o;
	if (!(this.cancel)
		&& (game == null || !(game.getClass() == control.getBoard()
			.getGame().getClass()))) {
	    showError(1);
	    game = null;
	} else if (!(this.cancel)
		&& !(game.getColumns() == control.getBoard().getGame()
			.getColumns())) {
	    showError(2);
	    game = null;
	}
	this.cancel = false;

	if (!(game == null)) {
	    this.control.getBoard().setGame(game);
	    this.control.clearStack();
	}
    }

    private Object readSavegameObject() {
	Object savegame = null;

	try {
	    File file = new File(this.fileDialog(false));
	    if (!file.exists()) {
		JOptionPane.showMessageDialog(control,
			"Datei existiert nicht!", "Fehler", 0);
		this.cancel = true;
	    }
	    FileInputStream fstream = null;
	    ObjectInputStream ostream = null;
	    try {
		fstream = new FileInputStream(file);
		ostream = new ObjectInputStream(fstream);
		savegame = ostream.readObject();
	    } catch (Exception e) {
		savegame = null;
	    } finally {
		if (fstream != null)
		    fstream.close();
		if (ostream != null)
		    ostream.close();
	    }
	} catch (Exception e) {
	}

	return savegame;
    }

    private void showError(int mode) {
	if (mode == 1)
	    JOptionPane.showMessageDialog(control, "Datei ist kein \""
		    + control.getName() + "\" Savegame", "Fehler", 0);
	if (mode == 2)
	    JOptionPane.showMessageDialog(control, "Spielstand ist kein "+control.getBoard().getGame()
			.getColumns()+"x"+control.getBoard().getGame()
			.getColumns()+" Board",
		    "Fehler", 0);
    }

    private void writeSavegameFile(RegularGame<M> game) throws RuntimeException {
	File file = new File(this.fileDialog(true));

	try {
	    FileOutputStream fstream = null;
	    ObjectOutputStream ostream = null;
	    try {
		fstream = new FileOutputStream(file);
		ostream = new ObjectOutputStream(fstream);
		ostream.writeObject(this.control.getBoard().getGame());

	    } catch (Exception e) {
		e.printStackTrace();

		throw new RuntimeException("Speichern fehlgeschlagen.", e);
	    } finally {
		if (fstream != null)
		    fstream.close();
		if (ostream != null)
		    ostream.close();
	    }
	} catch (Exception e) {
	    throw new RuntimeException("Fehler bei Dateierstellung." + e);
	}
    }

    private String fileDialog(boolean save) {
	final class FileNameFilter extends FileFilter {
	    public boolean accept(File f) {
		if (f.isDirectory())
		    return true;
		if (f.getName().endsWith("sav"))
		    return true;
		return false;
	    }

	    public String getDescription() {
		return "Savegames (*.sav)";
	    }
	}

	try {
	    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
	} catch (Exception e) {
	    e.printStackTrace();
	}

	JFileChooser jfc = new JFileChooser("./src/a02/savegames/");
	jfc.setFileFilter(new FileNameFilter());
	jfc.setAcceptAllFileFilterUsed(false);
	// FileView view = new IconView();
	int selection = 0;
	File tmp = null;
	String tmpName = null;

	if (save) {
	    selection = jfc.showSaveDialog(this.control);
	} else {
	    selection = jfc.showOpenDialog(this.control);
	}

	if (selection == JFileChooser.APPROVE_OPTION) {
	    tmp = jfc.getSelectedFile();
	    try {
		tmpName = tmp.getCanonicalPath();
	    } catch (IOException e) {
	    }
	} else if (selection == JFileChooser.CANCEL_OPTION) {
	    this.cancel = true;
	}

	if (!(tmp.getName().contains(".sav")))
	    tmpName += ".sav";
	if (save && !(tmpName.contains("(" + control.getName() + ")")))
	    tmpName = tmpName.substring(0, tmpName.length() - 4) + "("
		    + control.getName() + ").sav";
	return tmpName;
    }

}
